package com.jay.aopproxy;

import com.jay.aop.exception.MinimumAccountException;
import com.jay.aopproxy.config.CGLIBProxyConfig;
import com.jay.aopproxy.config.JDKProxyConfig;
import com.jay.aopproxy.model.Account;
import com.jay.aopproxy.service.AccountService;
import com.jay.aopproxy.service.impl.AccountServiceImpl;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ProxyTest {
    private static final Logger LOGGER = Logger.getLogger(ProxyTest.class);

    @Test
    public void testAopProxyPerformance() throws MinimumAccountException {
        int countObjects = 5000;
        AccountServiceImpl[] unproxiedClasses = new AccountServiceImpl[countObjects];
        for (int i = 0; i < countObjects; i++) {
            unproxiedClasses[i] = new AccountServiceImpl();
        }
        AccountService[] cglibProxyClasses = new AccountService[countObjects];
        AccountService accountService = null;
        for (int i = 0; i < countObjects; i++) {
            accountService = new AnnotationConfigApplicationContext(CGLIBProxyConfig.class).getBean(AccountService.class);
            cglibProxyClasses[i] = accountService;
        }
        AccountService[] jdkProxyClasses = new AccountService[countObjects];
        for (int i = 0; i < countObjects; i++) {
            accountService = new AnnotationConfigApplicationContext(JDKProxyConfig.class).getBean(AccountService.class);
            jdkProxyClasses[i] = accountService;
        }

        long noProxy = invokeTargetObjects(countObjects, unproxiedClasses);
        displayResults("NOProxy",noProxy);
        long jdkProxy = invokeTargetObjects(countObjects, jdkProxyClasses);
        displayResults("JDKProxy",jdkProxy);
        long cglibProxy = invokeTargetObjects(countObjects, cglibProxyClasses);
        displayResults("cglibProxy",cglibProxy);

    }
    private void displayResults(String label, long timeTook) {
        LOGGER.info(label + ": " + timeTook + "(ns) " + (timeTook / 1000000) + "(ms)");
    }
    private long invokeTargetObjects(int countObjects,AccountService[] classes) throws MinimumAccountException {
        long start = System.nanoTime();
        Account source = new Account(101,"Account1");
        Account dest = new Account(102,"Account2");
        for (int i = 0; i < countObjects; i++) {
            classes[i].doAccountTransaction(source, dest, 100);
        }
        long end = System.nanoTime();
        return end - start;
    }
}
